package com.dyna.core.utils;

import com.alibaba.fastjson.JSON;
import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.auth0.jwt.interfaces.JWTVerifier;
import com.dyna.constants.SysConstant;
import com.dyna.constants.TokenConstant;
import com.dyna.core.exception.CustomException;
import com.dyna.domain.dto.UserDto;
import lombok.extern.slf4j.Slf4j;

import java.util.Date;
import java.util.Optional;

/**
 * Description: jwt的token生成与解析
 * Author: <a href="https://github.com/zongzibinbin">abin</a>
 * Date: 2023-04-03
 * @author Admin
 */
@Slf4j
public  class JwtUtil {

    private static final String USER_CLAIM = "user";
    private static final String CREATE_TIME = "createTime";

    /**
     * JWT生成Token.<br/>
     * <p>
     * JWT构成: header, payload, signature
     */
    public static String createToken(String user) {
        // build token
        return JWT.create()
                // 只存一个uid信息，其他的自己去redis查
                .withClaim(USER_CLAIM, user)
                .withClaim(CREATE_TIME, new Date())
                // 设置过期时间
//                .withExpiresAt(new Date(System.currentTimeMillis() + AppConstant.JWT_EXPIRE))
                // signature
                .sign(Algorithm.HMAC256(TokenConstant.JWT_SECRET));
    }

    public static void main(String[] args) {
        UserDto dto = new UserDto();
        dto.setUsername("测试");
        dto.setAge(33);
        String token = createToken(JSON.toJSONString(dto));
        System.out.println("生成token:" + token);
        UserDto userDto = verifyToken(token);
        System.out.println(userDto);
    }

    /**
     * 解密Token
     */
    public static UserDto verifyToken(String token) {
        Optional.ofNullable(token).orElseThrow(()-> new CustomException(SysConstant.TOKEN_NOT_NULL));
        try {
            JWTVerifier verifier = JWT.require(Algorithm.HMAC256(TokenConstant.JWT_SECRET)).build();
            DecodedJWT jwt = verifier.verify(token);
            return Optional.ofNullable(jwt)
                    .map(DecodedJWT::getClaims)
                    .map(map -> map.get(USER_CLAIM))
                    .map(Claim::asString)
                    .map(userStr -> JSON.parseObject(userStr, UserDto.class))
                    .orElseThrow(()-> new CustomException(SysConstant.AUTHORIZATION_ERROR_INFO));
        } catch (Exception e) {
            throw new CustomException(SysConstant.LOGIN_EXPIRE_INFO);
        }
    }

}
